package ru.romannep.and.chopperbattle;

//import java.awt.geom.Rectangle2D;
import java.util.ArrayList;
import ru.romannep.pc.chopperbattle.ChopperBattleGameEngine;
import ru.romannep.pc.chopperbattle.DestroyAnim;
import ru.romannep.pc.chopperbattle.GameChopperCommand;
import ru.romannep.pc.chopperbattle.GameElement;
import ru.romannep.pc.chopperbattle.MovingGameElement;
import ru.romannep.pc.chopperbattle.StartPlaces;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.util.Log;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;

public class GameView extends SurfaceView implements SurfaceHolder.Callback {

	private final Game game; // activivty
	private ViewThread viewThread;

	private int width, height;

	private int[][] touchInputs = new int[4][3]; // хранит по каждому контролу:
													// pid, и x,y центра
	private static final int UP_INPUT = 0;
	private static final int RIGHT_INPUT = 1;
	private static final int LEFT_INPUT = 2;
	private static final int FIRE_INPUT = 3;

	public ChopperBattleGameEngine gameEngine; // для доступа из треда

	private static final int FIELD_TITLE_HEIGHT = 16;
	private float scale;
	private int fieldXPosition;

    private Bitmap field;
    private Bitmap fieldTitle;
    private Bitmap title;
    private Bitmap[] chop1img = new Bitmap[24];
    private Bitmap[] chop2img = new Bitmap[24];
    private Bitmap[] destroyimg = new Bitmap[6];
    private int chop1imgIndex = 0;
    private int chop2imgIndex = 0;
	private Bitmap tempBitmap;
    private static final int WINTEXTCYCLES = 50; //количество циклов таймера для отображения победителя при окончании игры
    private int wintextcycles = WINTEXTCYCLES;
    private static final int FUEL_1_POS_X = 137;
    private static final int FUEL_2_POS_X = 523;
    private static final int FUEL_SIZE_X = 67;
    private static final int FUEL_SIZE_Y = 9;
    private static final int FUEL_POS_Y = 3;

    
    
	// временно - для тестов
	public StartPlaces startPlaces;

	private Bitmap testBitmap, testBitmap2;

	ArrayList<GameElement> borders = new ArrayList<GameElement>();
	ArrayList<GameElement> objects = new ArrayList<GameElement>(); // все
																	// объекты
																	// на поле,
																	// для
																	// проверки
																	// столкновений
	public static final float CHOPPER_SIZE_X = 32f;
	public static final float CHOPPER_SIZE_Y = 22f;
	public static final float CHOPPER_CRITICAL_SPEED = 50f;
	public static final float ACC_GRAVITY = 0.2f;
	public static final float ACC_CHOPPER_X = 0.2f;
	public static final float ACC_CHOPPER_Y = 0.4f;
	public static final float MAX_SPEED = 4f;
	public static final float FIELD_BORDER_SIZE = 5f;
	private static final float BORDER_ELAST = 0;
	private static final int TOUCH_INPUT_RADIUS = 40;
	MovingGameElement chopper1;

	//стянуто http://thinkandroid.wordpress.com/2009/12/25/resizing-a-bitmap/
	public Bitmap getResizedBitmap(Bitmap bm,  int newWidth, int newHeight) {

		int width = bm.getWidth();

		int height = bm.getHeight();

		float scaleWidth = ((float) newWidth) / width;

		float scaleHeight = ((float) newHeight) / height;

		// create a matrix for the manipulation

		Matrix matrix = new Matrix();

		// resize the bit map

		matrix.postScale(scaleWidth, scaleHeight);

		// recreate the new Bitmap

		Bitmap resizedBitmap = Bitmap.createBitmap(bm, 0, 0, width, height,
				matrix, false);

		return resizedBitmap;

	}

	public GameView(Context context) {
		super(context);

		game = (Game) context;
		getHolder().addCallback(this);
		viewThread = new ViewThread(this);

		setFocusable(true);
		setFocusableInTouchMode(true);

		gameEngine = new ChopperBattleGameEngine();
		Log.v(ChopperBattleMain.TAG, "TRYING load level in gameEngine");
		gameEngine.loadLevel(getResources().openRawResource(R.raw.level1));
		gameEngine.gameStart();
		Log.v(ChopperBattleMain.TAG, "Done init gE");

		
//		Log.v(ChopperBattleMain.TAG, "TRYING load level");
//		try {
//			ObjectInputStream in = new ObjectInputStream(getResources()
//					.openRawResource(R.raw.level1));
//			String levelName = (String) in.readObject();
//			startPlaces = (StartPlaces) in.readObject();
//			borders = (ArrayList<GameElement>) in.readObject();
//
//		} catch (ClassNotFoundException ex) {
//			Log.v(ChopperBattleMain.TAG, "EX! class not fount");
//		} catch (IOException ex) {
//			Log.v(ChopperBattleMain.TAG, "EX! i o");
//		} catch (ClassCastException ex) {
//			Log.v(ChopperBattleMain.TAG, "EX! class cast");
//		}		 

	}

	public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2, int arg3) {

	}

	public void surfaceCreated(SurfaceHolder arg0) {

		if (!viewThread.isRunning()) {
			viewThread = new ViewThread(this);
			viewThread.setRunning(true);
			viewThread.start();
		}

	}

	public void surfaceDestroyed(SurfaceHolder arg0) {

		Log.v(ChopperBattleMain.TAG, "surface destroyed");

		if (viewThread.isRunning()) {

			boolean retry = true;

			viewThread.setRunning(false);
			while (retry) {
				try {
					viewThread.join();
					retry = false;
				} catch (InterruptedException e) {
				}
			}

		}

	}

	@Override
	protected void onDraw(Canvas canvas) {

		// Paint testPaint = new Paint();
		// testPaint.setColor(0xffffffff);
		// canvas.drawRect(10, 10, 40, 40, testPaint);
		// canvas.drawBitmap(testBitmap, 50, 50, null);

	}

	public void doDraw(Canvas canvas) {

		//очистим все
		canvas.drawColor(Color.BLACK);

		Paint localPaint = new Paint();
		localPaint.setColor(0xff000000);
		
		//поле
		canvas.drawBitmap(field, fieldXPosition, FIELD_TITLE_HEIGHT, null);
		canvas.drawBitmap(fieldTitle, fieldXPosition, 0, null);

		
		//вертолеты и пули
        if (gameEngine.chopper1.inGame) {
            canvas.drawRect(fieldXPosition + FUEL_1_POS_X*scale - scale*(ChopperBattleGameEngine.FUEL_CAPACITY - gameEngine.chopper1.fuel) / ChopperBattleGameEngine.FUEL_CAPACITY * FUEL_SIZE_X, FUEL_POS_Y, fieldXPosition + FUEL_1_POS_X*scale , FUEL_POS_Y + FUEL_SIZE_Y, localPaint);
        	canvas.drawBitmap(chop1img[chop1imgIndex + (gameEngine.chopper1.directionRight ? 0 : 12)],
                    (int) (fieldXPosition + gameEngine.chopper1.x*scale), (int) (FIELD_TITLE_HEIGHT + gameEngine.chopper1.y*scale),
                    null);

        }
        if (gameEngine.chopper2.inGame) {
            //g2.fill(new Rectangle2D.Float(FUEL_2_POS_X - (ge2.FUEL_CAPACITY - ge2.chopper2.fuel) / ge2.FUEL_CAPACITY * FUEL_SIZE_X, FUEL_POS_Y, (ge2.FUEL_CAPACITY - ge2.chopper2.fuel) / ge2.FUEL_CAPACITY * FUEL_SIZE_X, FUEL_SIZE_Y));
            canvas.drawRect(fieldXPosition + FUEL_2_POS_X*scale - scale*(ChopperBattleGameEngine.FUEL_CAPACITY - gameEngine.chopper2.fuel) / ChopperBattleGameEngine.FUEL_CAPACITY * FUEL_SIZE_X, FUEL_POS_Y, fieldXPosition + FUEL_2_POS_X*scale , FUEL_POS_Y + FUEL_SIZE_Y, localPaint);
        	canvas.drawBitmap(chop2img[chop2imgIndex + (gameEngine.chopper2.directionRight ? 0 : 12)],
                    (int) (fieldXPosition + gameEngine.chopper2.x*scale), (int) (FIELD_TITLE_HEIGHT + gameEngine.chopper2.y*scale),
                    null);
        }
        //%%% счет
//        g2.drawString("" + ge2.chopper1drops + "(" + ge2.MAX_DROPS + ")", DROPS_1_POS_X, DROPS_POS_Y);
//        g2.drawString("" + ge2.chopper2drops + "(" + ge2.MAX_DROPS + ")", DROPS_2_POS_X, DROPS_POS_Y);
        
        //отрисовка пуль
		localPaint.setColor(0xffffffff);
        for (GameElement obj : gameEngine.bullets) {
            canvas.drawRect(fieldXPosition + obj.x*scale, FIELD_TITLE_HEIGHT + obj.y*scale, 
            		fieldXPosition + (obj.x+obj.sx)*scale, FIELD_TITLE_HEIGHT + (obj.y+obj.sy)*scale, localPaint);
            canvas.drawRect(fieldXPosition + obj.x*scale, FIELD_TITLE_HEIGHT + obj.y*scale, 
            		fieldXPosition + (obj.x)*scale+1, FIELD_TITLE_HEIGHT + (obj.y)*scale+1, localPaint);
            //.draw(new Rectangle2D.Float(FIELD_POS_X + obj.x, FIELD_POS_Y + obj.y, obj.sx, obj.sy));
        }
        //отрисовка анимации взрыва вертолета
        for (DestroyAnim da : gameEngine.destroy) {
        	canvas.drawBitmap(destroyimg[da.count],
                    (int) (fieldXPosition + da.x*scale), (int) (FIELD_TITLE_HEIGHT+da.y*scale),
                    null);
        }

        //%%%отрисовка сообщения о победителе
//        if (ge2.winnerText != "") {
//            g2.fill(winnerRect);
//            g2.setColor(new Color(0, 0, 0));
//            g2.drawString(ge2.winnerText, WINNER_TEXT_X, WINNER_TEXT_Y);
//        }
		
		
		
// можно раскоментить для вида без графики		
//		for (GameElement ge : gameEngine.objects) {
//			canvas.drawRect(fieldXPosition + ge.x * scale, FIELD_TITLE_HEIGHT
//					+ ge.y * scale, fieldXPosition + (ge.x + ge.sx) * scale,
//					FIELD_TITLE_HEIGHT + (ge.y + ge.sy) * scale, localPaint);
//		}
        
        
        
		//элементы управления
		localPaint.setColor(0xffffffff);
		for (int i = 0; i < touchInputs.length; i++) {
			localPaint.setColor(getResources().getColor(
					touchInputs[i][0] == -1 ? R.color.touch_input
							: R.color.touch_input_pressed));
			canvas.drawCircle(touchInputs[i][1], touchInputs[i][2],
					TOUCH_INPUT_RADIUS, localPaint);
		}
        

		//временно - для тестов
//		canvas.drawBitmap(testBitmap, chopper1.x, chopper1.y, null);

        // canvas.drawRect(100, 100, 140, 140, testPaint);
		// canvas.drawBitmap(testBitmap, 50, 50, null);
		// canvas.drawBitmap(testBitmap2,chopper1.x+50, chopper1.y, null);

	}

	@Override
	protected void onSizeChanged(int w, int h, int oldw, int oldh) {
		super.onSizeChanged(w, h, oldw, oldh);
		width = w;
		height = h;
		Log.v(ChopperBattleMain.TAG, "new view size: w=" + width + " h="
				+ height);
		initGameView();

	}

	public void testGameCycle() {//выполняет игровой цикл. вызывается из треда отрисовки

        if (gameEngine.gameRunning) {

            //двигаем кадры анимации вертолетов
            //если у вертолета двигатель запущен, то анимация идет быстрей
            chop1imgIndex++;
            if (gameEngine.chopper1.engineOn()) {
                chop1imgIndex++;
            }
            chop1imgIndex = chop1imgIndex > 11 ? chop1imgIndex - 12 : chop1imgIndex;
            chop2imgIndex++;
            if (gameEngine.chopper2.engineOn()) {
                chop2imgIndex++;
            }
            chop2imgIndex = chop2imgIndex > 11 ? chop2imgIndex - 12 : chop2imgIndex;

            //вызываем выполнение игрового цикла
            gameEngine.gameCycle();

        } else {
            wintextcycles++;
        }

        //обработка счетчика времени показа победителя
        if (wintextcycles > WINTEXTCYCLES) {
        	//%%% вернуться
        }
		
		//временно для тестов
//		chopper1.move(1f, borders);

	}

	public void initGameView() {

		// Инициализация тач кнопок
		touchInputs[UP_INPUT][1] = TOUCH_INPUT_RADIUS;
		touchInputs[UP_INPUT][2] = height - TOUCH_INPUT_RADIUS;

		touchInputs[LEFT_INPUT][1] = width - TOUCH_INPUT_RADIUS * 4;
		touchInputs[LEFT_INPUT][2] = height - TOUCH_INPUT_RADIUS;

		touchInputs[RIGHT_INPUT][1] = width - TOUCH_INPUT_RADIUS;
		touchInputs[RIGHT_INPUT][2] = height - TOUCH_INPUT_RADIUS;

		touchInputs[FIRE_INPUT][1] = width - (int) (TOUCH_INPUT_RADIUS * 2.5f);
		touchInputs[FIRE_INPUT][2] = height - TOUCH_INPUT_RADIUS * 3;

		for (int i = 0; i < touchInputs.length; i++) {
			touchInputs[i][0] = -1;
		}


		// Загрузка и ресайз картинок

		// Вычисляем коэф. ресайза
		float scale_width = width / ChopperBattleGameEngine.FIELD_SIZE_X;
		float scale_heiht = (height - FIELD_TITLE_HEIGHT)
				/ ChopperBattleGameEngine.FIELD_SIZE_Y;
		scale = scale_heiht < scale_width ? scale_heiht : scale_width;
		fieldXPosition = (int) ((width - ((float) ChopperBattleGameEngine.FIELD_SIZE_X)
				* scale) / 2);

		
		tempBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.field1);
		field = getResizedBitmap(tempBitmap, width -fieldXPosition*2, height - FIELD_TITLE_HEIGHT );
		
		tempBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.field_title);
		fieldTitle = getResizedBitmap(tempBitmap, width -fieldXPosition*2, FIELD_TITLE_HEIGHT );

		// спрайтов всего 6, но чтоб пропеллер крутился туда-обратно - добавляем
		// ссылками еще 6 и еще 12 для отражения
		Matrix reflectMatrix = new Matrix();
		reflectMatrix.setScale(-1, 1);
        reflectMatrix.postTranslate(ChopperBattleGameEngine.CHOPPER_SIZE_X*scale, 0);

        for (int i = 0; i < 6; i++) {
    		tempBitmap = BitmapFactory.decodeResource(getResources(), getResources().getIdentifier("chop1_" + i, "drawable", "ru.romannep.and.chopperbattle") );
            chop1img[i] = getResizedBitmap(tempBitmap, (int) (ChopperBattleGameEngine.CHOPPER_SIZE_X*scale), (int) (ChopperBattleGameEngine.CHOPPER_SIZE_Y*scale));
            chop1img[i+12] = Bitmap.createBitmap(chop1img[i], 0, 0,
            		chop1img[i].getWidth(), chop1img[i].getHeight(), reflectMatrix,
            		true); 
        }
        
        
        for (int i = 0; i < 6; i++) {
            chop1img[6 + i] = chop1img[5 - i];
            chop1img[18 + i] = chop1img[17 - i];
        }
        for (int i = 0; i < 6; i++) {
    		tempBitmap = BitmapFactory.decodeResource(getResources(), getResources().getIdentifier("chop2_" + i, "drawable", "ru.romannep.and.chopperbattle") );
            chop2img[i] = getResizedBitmap(tempBitmap, (int) (ChopperBattleGameEngine.CHOPPER_SIZE_X*scale), (int) (ChopperBattleGameEngine.CHOPPER_SIZE_Y*scale));
            chop2img[i+12] = Bitmap.createBitmap(chop2img[i], 0, 0,
            		chop2img[i].getWidth(), chop2img[i].getHeight(), reflectMatrix,
            		true); 
        }
        for (int i = 0; i < 6; i++) {
            chop2img[6 + i] = chop2img[5 - i];
            chop2img[18 + i] = chop2img[17 - i];
        }
        for (int i = 0; i < 6; i++) {
    		tempBitmap = BitmapFactory.decodeResource(getResources(), getResources().getIdentifier("destroy_" + i, "drawable", "ru.romannep.and.chopperbattle") );
    		destroyimg[5 - i] = getResizedBitmap(tempBitmap, (int) (ChopperBattleGameEngine.CHOPPER_SIZE_X*scale), (int) (ChopperBattleGameEngine.CHOPPER_SIZE_Y*scale));
        }
		
		
		//временно - для тестов
		tempBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.chop1_3);
		
		testBitmap = getResizedBitmap(tempBitmap, (int) (ChopperBattleGameEngine.CHOPPER_SIZE_X*scale),(int) (ChopperBattleGameEngine.CHOPPER_SIZE_Y*scale));

//		testBitmap = BitmapFactory.decodeResource(getResources(),
//		R.drawable.chop1_0);
////отражение
//Matrix scaleMatrix = new Matrix();
//scaleMatrix.setScale(-1, 1);
//scaleMatrix.postTranslate(testBitmap.getWidth(), 0);
//
//testBitmap2 = Bitmap.createBitmap(testBitmap, 0, 0,
//		testBitmap.getWidth(), testBitmap.getHeight(), scaleMatrix,
//		true);

		borders.add(new GameElement(0, -FIELD_BORDER_SIZE, width,
				FIELD_BORDER_SIZE, BORDER_ELAST)); // top
		borders.add(new GameElement(0, height, width, FIELD_BORDER_SIZE,
				BORDER_ELAST)); // bottom
		borders.add(new GameElement(-FIELD_BORDER_SIZE, 0, FIELD_BORDER_SIZE,
				height, BORDER_ELAST)); // left
		borders.add(new GameElement(width, 0, FIELD_BORDER_SIZE, height,
				BORDER_ELAST)); // right

		chopper1 = new MovingGameElement(0, 10, 10, CHOPPER_SIZE_X,
				CHOPPER_SIZE_Y, 0, 0, 0, 0, ACC_GRAVITY);

		objects.addAll(borders);
		objects.add(chopper1);

	}

	@Override
	public boolean onTouchEvent(MotionEvent event) {

		int action = event.getAction();
		int actionCode = action & MotionEvent.ACTION_MASK;

		int pointerIndex = (action & MotionEvent.ACTION_POINTER_INDEX_MASK) >> MotionEvent.ACTION_POINTER_INDEX_SHIFT;
		int pid = event.getPointerId(pointerIndex);

		// Log.v(ChopperBattleMain.TAG, "! action " + action + " actionCode " +
		// actionCode + " pid " + pid);
		if (actionCode == MotionEvent.ACTION_DOWN
				|| actionCode == MotionEvent.ACTION_POINTER_DOWN) {
			Log.v(ChopperBattleMain.TAG, "action " + action + " actionCode "
					+ actionCode + " pid " + pid);
			Log.v(ChopperBattleMain.TAG, "Pressed pid=" + pid);
            GameChopperCommand chopper1command = GameChopperCommand.NULL;
//            GameChopperCommand chopper2command = GameChopperCommand.NULL;

            // нажали, узнаем что именно
			
			for (int i = 0; i < touchInputs.length; i++) {
				if (Math.sqrt((touchInputs[i][1] - event.getX(pid))
						* (touchInputs[i][1] - event.getX(pid))
						+ (touchInputs[i][2] - event.getY(pid))
						* (touchInputs[i][2] - event.getY(pid))) < TOUCH_INPUT_RADIUS) {
					touchInputs[i][0] = pid;

					// обработаем событие
					switch (i) {
					case UP_INPUT:
						chopper1.accY = ACC_GRAVITY - ACC_CHOPPER_Y;
                        chopper1command = GameChopperCommand.UP_ON;
						break;
					case LEFT_INPUT:
						chopper1.accX = -ACC_CHOPPER_X;
                        chopper1command = GameChopperCommand.LEFT_ON;
						break;
					case RIGHT_INPUT:
						chopper1.accX = ACC_CHOPPER_X;
                        chopper1command = GameChopperCommand.RIGHT_ON;
						break;
					case FIRE_INPUT:
						chopper1.accX = ACC_CHOPPER_X;
                        chopper1command = GameChopperCommand.FIRE;
						break;

					default:
						break;
					}

					break;
				}
			}

			if (chopper1command != GameChopperCommand.NULL) {
                gameEngine.chopperCommand(gameEngine.chopper1, chopper1command);
            }
//            if (chopper2command != GameChopperCommand.NULL) {
//            	gameEngine.chopperCommand(gameEngine.chopper2, chopper2command);
//            }
			

		} else if (actionCode == MotionEvent.ACTION_UP
				|| actionCode == MotionEvent.ACTION_POINTER_UP) {

			GameChopperCommand chopper1command = GameChopperCommand.NULL;
			
			// отпустили кнопку, очистим
			Log.v(ChopperBattleMain.TAG, "action " + action + " actionCode "
					+ actionCode + " pid " + pid);
			Log.v(ChopperBattleMain.TAG, "Released pid=" + pid);

			for (int i = 0; i < touchInputs.length; i++) {
				if (touchInputs[i][0] == pid) {
					touchInputs[i][0] = -1;
					// Обработаем событие
					switch (i) {
					case UP_INPUT:
						chopper1.accY = ACC_GRAVITY;
                        chopper1command = GameChopperCommand.UP_OFF;
						break;
					case LEFT_INPUT:
                        chopper1command = GameChopperCommand.LEFT_OFF;
						chopper1.accX = 0;
						break;
					case RIGHT_INPUT:
						chopper1.accX = 0;
                        chopper1command = GameChopperCommand.RIGHT_OFF;
						break;

					default:
						break;
					}

					break;
				} /* else if (touchInputs[i][0] != -1) {touchInputs[i][0]--;} */
			}
			if (chopper1command != GameChopperCommand.NULL) {
                gameEngine.chopperCommand(gameEngine.chopper1, chopper1command);
            }

		}

		return true;
	}
}
